package com.android.adpater;


import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import com.android.adpater.interfaces.IAdapter;
import com.android.adpater.interfaces.IData;
import com.android.adpater.interfaces.IScrollHideListener;
import com.android.adpater.interfaces.OnClickListItemListener;

import java.util.ArrayList;
import java.util.List;


/**
 *
 * @author GYL
 * @version 1.0
 * BaseRecyclerAdapter 基类
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class BaseRecyclerAdapter<T>
        extends RecyclerView.Adapter<BaseRecyclerAdapter.RecyclerViewHolder> implements IAdapter<T>, IData<T> {

    protected final Context mContext;
    private final List<T> mData;

    private boolean enableNotifyDataSetChanged = true;
    private boolean isRecyclable = true;

    @Override
    public void setOnListItemClick(@NonNull OnClickListItemListener onItemViewClick) {
        this.mOnClickListItemListener = onItemViewClick;
    }

    protected OnClickListItemListener mOnClickListItemListener;

    protected OnItemClickListener mItemClickListener;
    protected OnItemLongClickListener mItemLongClickListener;

    public BaseRecyclerAdapter(@NonNull Context context) {
        this(context, -1, null);
    }

    public BaseRecyclerAdapter(@NonNull Context context, int layoutResId, List<T> data) {
        this.mData = data == null ? new ArrayList<T>() : new ArrayList<>(data);
        this.mContext = context;
    }

    @Override
    public String getString(@StringRes int strId, Object... obj) {
        if (obj == null) {
            return mContext.getString(strId);
        } else {
            return mContext.getString(strId, obj);
        }
    }

    @Override
    public @ColorInt
    int getColor(@ColorRes int colorId) {
        return AdapterViewHelper.getColor(mContext, colorId);
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //final AdapterViewHelper helper = AdapterViewHelper.get(mContext, null , parent, viewType, -1);
        final AdapterViewHelper helper = AdapterViewHelper.get(mContext,
                null,
                parent,
                getLayoutResId(viewType),
                -1);

        return new RecyclerViewHolder(helper);
    }

    @Override
    public void onBindViewHolder(BaseRecyclerAdapter.RecyclerViewHolder holder, int position) {
        //不使用缓存
        if (!this.isRecyclable) {
            holder.setIsRecyclable(this.isRecyclable);
        }
        AdapterViewHelper helper = holder.mAdapterHelper;
        helper.setAssociatedObject(getItem(position));
        //applyChildViewListeners(helper, holder.getAdapterPosition());
        onBindView(helper, getItem(position), position);
    }

    @Override
    public void onBindViewHolder(BaseRecyclerAdapter.RecyclerViewHolder holder, int position, List<Object> payloads) {
        if (null != payloads && payloads.size() > 0) {
            AdapterViewHelper helper = holder.mAdapterHelper;
            helper.setAssociatedObject(getItem(position));
            onItemContentChanged(helper, payloads);
        } else {
            super.onBindViewHolder(holder, position, payloads);
        }
    }

    @Override
    public void enableNotifyDataSetChanged(boolean enable) {
        this.enableNotifyDataSetChanged = enable;
    }

    /**
     * 清除缓存
     */
    @Override
    public void onViewRecycled(@NonNull BaseRecyclerAdapter.RecyclerViewHolder holder) {
        super.onViewRecycled(holder);
    }

    @Override
    public final int getItemViewType(int position) {
        //return super.getItemViewType(position);
        //return getLayoutResId(getItem(position), position);
        return getItemViewType(getItem(position), position);
    }

    /**
     * View 显示规则定义
     *
     * @param item
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(T item, int position) {
        return super.getItemViewType(position);
    }

    //<editor-fold desc=" IDATA ....... ">


    @Override
    public int getCount() {
        return mData == null ? 0 : mData.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemCount() {
        return getCount();
    }

    @Override
    public List<T> getData() {
        return mData;
    }

    @Override
    public void add(@NonNull T item) {
        mData.add(item);
        if (enableNotifyDataSetChanged) {
            notifyItemInserted(mData.size());
        }
    }

    @Override
    public void insert(int position, @NonNull T item) {
        mData.add(position, item);
        if (enableNotifyDataSetChanged) {
            notifyItemInserted(mData.size());
        }
    }

    @Override
    public void addAll(@NonNull List<T> list) {
        if (list == null) {
            return;
        }
        mData.addAll(list);
        if (enableNotifyDataSetChanged) {
            notifyItemRangeInserted(mData.size() - list.size(), list.size());
        }
    }

    @Override
    public void set(@NonNull T oldItem, @NonNull T newItem) {
        set(mData.indexOf(oldItem), newItem);
    }

    @Override
    public void set(int index, @NonNull T item) {
        if (index >= 0 && index < getItemCount()) {
            mData.set(index, item);
            if (enableNotifyDataSetChanged) {
                notifyItemChanged(index);
            }
        }
    }

    @Override
    public void remove(@NonNull T item) {
        remove(mData.indexOf(item));
    }

    @Override
    public void remove(int index) {
        if (index >= 0 && index < getItemCount()) {
            mData.remove(index);
            if (enableNotifyDataSetChanged) {
                notifyItemRemoved(index);
            }
        }
    }

    @Override
    public void replaceAll(@NonNull List<T> item) {
        replaceAll(item, true);
    }

    /**
     * 替换数据
     *
     * @param item                 新数据列表
     * @param notifyDataSetChanged 是否执行：notifyItem...方法
     */
    public void replaceAll(@NonNull List<T> item, boolean notifyDataSetChanged) {
        if (notifyDataSetChanged) {
            clear();
            addAll(item);
        } else {
            mData.clear();
            mData.addAll(item);
        }
    }

    @Override
    public boolean contains(@NonNull T item) {
        return mData.contains(item);
    }

    @Override
    public void clear() {
        final int size = mData.size();
        mData.clear();
        notifyItemRangeRemoved(0, size);
    }

    @Override
    public void setData(@NonNull List<T> list) {
        mData.clear();
        mData.addAll(list);
        notifyDataSetChanged();
    }

    @Override
    public void addArray(@NonNull T[] datas) {
        for (T data : datas) {
            mData.add(data);
        }
        notifyDataSetChanged();
    }

    @Override
    public T getItem(int position) {
        return position < 0 || position >= mData.size() ? null : mData.get(position);
    }

    //</editor-fold>

    /**
     * ViewHolder创建时回调
     */
    public void onCreate(RecyclerView.ViewHolder viewHolder, AdapterViewHelper helper) {
        //super.onCreate();
    }

    public void setIsRecyclable(boolean isRecyclable) {
        this.isRecyclable = isRecyclable;
    }

    /**
     * 更小粒度的更新，比如某个对象的某个属性值改变了，只改变此属性
     * <pre>
     * 此回调执行的前提是：
     * 使用 {@link android.support.v7.util.DiffUtil.Callback} 进行数据更新，
     * 并且重写了 {@link android.support.v7.util.DiffUtil.Callback#getChangePayload} 方法
     * 使用方法见：<a href="https://github.com/qyxxjd/CommonAdapter/blob/master/app/src/main/java/com/classic/adapter/simple/activity/RecyclerViewSimpleActivity.java">RecyclerViewSimpleActivity</a>
     * </pre>
     *
     * @param helper   {@link AdapterViewHelper}
     * @param payloads {@link RecyclerView.Adapter#onBindViewHolder}
     */
    public void onItemContentChanged(@NonNull AdapterViewHelper helper, @NonNull List<Object> payloads) {
    }

    public void setOnItemClickListener(OnItemClickListener itemClickListener) {
        this.mItemClickListener = itemClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener itemLongClickListener) {
        this.mItemLongClickListener = itemLongClickListener;
    }

    @Override
    public void addItemClick(@NonNull View view, final Object obj, @NonNull final int position) {
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnClickListItemListener != null) {
                    mOnClickListItemListener.onPageViewItemClick(v, obj, position);
                }
            }
        });
    }

    public interface OnItemClickListener {
        /**
         * Item 点击事件
         *
         * @param view
         * @param position
         */
        void onItemClick(View view, int position);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClick(View view, int position);
    }

    protected final class RecyclerViewHolder extends RecyclerView.ViewHolder {
        AdapterViewHelper mAdapterHelper;

        public RecyclerViewHolder(AdapterViewHelper adapterHelper) {
            super(adapterHelper.getView());
            this.mAdapterHelper = adapterHelper;
            onCreate(this, adapterHelper);
            //
            if (null != mItemClickListener) {
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mItemClickListener.onItemClick(v, getAdapterPosition());
                    }
                });
            }
            if (null != mItemLongClickListener) {
                itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        return mItemLongClickListener.onItemLongClick(v, getAdapterPosition());
                    }
                });
            }
        }
    }

    public static abstract class AbsScrollControl extends RecyclerView.OnScrollListener implements IScrollHideListener {

        private static final int DEFAULT_SCROLL_HIDE_OFFSET = 20; //滑动隐藏的偏移量

        private int mCurrentScrollOffset;
        private boolean isControlVisible;

        /**
         * 自定义LayoutManager需要实现此方法
         */
        protected int getFirstVisibleItemPositions() {
            return 0;
        }

        /**
         * 获取滑动隐藏的偏移量
         */
        protected int getScrollHideOffset() {
            return DEFAULT_SCROLL_HIDE_OFFSET;
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            final int firstVisibleItemPosition = findFirstVisibleItemPosition(recyclerView.getLayoutManager());

            if (firstVisibleItemPosition == 0 && !isControlVisible) {
                onShow();
                isControlVisible = true;
            } else if (firstVisibleItemPosition != 0 && mCurrentScrollOffset > getScrollHideOffset() &&
                    isControlVisible) {
                //向上滚动,并且视图为显示状态
                onHide();
                isControlVisible = false;
                mCurrentScrollOffset = 0;
            } else if (firstVisibleItemPosition != 0 && mCurrentScrollOffset < -getScrollHideOffset() &&
                    !isControlVisible) {
                //向下滚动,并且视图为隐藏状态
                onShow();
                isControlVisible = true;
                mCurrentScrollOffset = 0;
            }

            //dy>0:向上滚动
            //dy<0:向下滚动
            if ((isControlVisible && dy > 0) || (!isControlVisible && dy < 0)) {
                mCurrentScrollOffset += dy;
            }
        }

        private int findFirstVisibleItemPosition(RecyclerView.LayoutManager layoutManager) {
            if (layoutManager instanceof GridLayoutManager) {
                return ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
            } else if (layoutManager instanceof LinearLayoutManager) {
                return ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            } else if (layoutManager instanceof StaggeredGridLayoutManager) {
                return ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null)[0];
            } else {
                return getFirstVisibleItemPositions();
            }
        }
    }
}
